home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 1.iso
/
toolbox
/
src
/
exampleCode
/
opengl
/
xlib
/
zrgb.c
< prev
Wrap
C/C++ Source or Header
|
1996-11-11
|
15KB
|
450 lines
/*
* Copyright (c) 1993-94, Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the name of Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
* POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
/*
* zrgb.c: an openGL-Xlib RGB, zbuffer example program.
*
* zrgb is the openGL "after" version of the IrisGL
* "before" program, ~4Dgifts/examples/grafix/zrgb.c
*
* - LEFTMOUSE: move the 3 polygons around a center
* - Esc key: exit
*
* This program demostrates zbuffering 3 intersecting RGB polygons while
* in doublebuffer mode where, movement of the mouse with the LEFTMOUSE
* button depressed will, rotate the 3 polygons via compound rotations
* allowing continuous screen-oriented rotations. (See orient(), and
* draw_scene() below). Notice that there is no wasted CPU usage when the
* user moves the mouse out of the window without holding down LEFTMOUSE--
* there is no "qtest" -type functionality being performed. Hence the
* program simply blocks on the XNextEvent statement.
*
* ratmandu -- ported to openGL, april 93
*/
#include <GL/glx.h>
#include <GL/glu.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#define TRUE 1
#define FALSE 0
Display *dpy; /* The X server connection */
Atom del_atom; /* WM_DELETE_WINDOW atom */
Window glwin; /* handle to the GL window */
XEvent event;
/* function declarations */
void openwindow(char *);
void resize_buffer(void);
void clean_exit(void);
void initGL(void);
void orient(void);
void drawScene(void);
void drawPolys(void);
static float objmat[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
};
int xsize, ysize; /* current size-of-window keepers */
double scrnaspect; /* aspect ratio value */
int xpos, ypos, oxpos, oypos; /* old and new mouse position */
main(argc,argv)
int argc;
char **argv;
{
int myExpose, myConfigure, myButtPress, myKeyPress;
int needToDraw = 0; /* don't set this to true until
we get our first Expose event */
myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
openwindow(argv[0]);
/* start out making the singlebuffer window be our current GL window */
initGL(); /* do GL init stuff */
/*
* The event loop.
*/
while (1) { /* standard logic: get event(s), process event(s) */
XEvent event;
KeySym keysym;
char buf[4];
/* this "do while" loop does the `get events' half of the "get events,
* process events" action of the infinite while. this is to ensure
* the event queue is always drained before the events that have come
* in are processed.
*/
do {
XNextEvent(dpy, &event);
switch (event.type) {
/* "Expose" events are sort of like "REDRAW" in gl-speak in
* terms of when a window becomes visible, or a previously
* invisible part becomes visible.
*/
case Expose: /* Exposures */
needToDraw = myExpose = TRUE;
break;
/* "ConfigNotify" events are like "REDRAW" in terms of changes
* to a window's size or position.
*/
case ConfigureNotify: /* Resize GL manually */
xsize = event.xconfigure.width;
ysize = event.xconfigure.height;
needToDraw = myConfigure = TRUE;
break;
/* Wait for "MotionNotify" events so the queue doesn't fill up
*/
case MotionNotify:
myButtPress = TRUE;
xpos = event.xmotion.x;
ypos = event.xmotion.y;
break;
/* "ClientMessage" is generated if the WM itself is being
* gunned down and sends an exit signal to any running prog.
*/
case ClientMessage:
if (event.xclient.data.l[0] == del_atom)
clean_exit();
break;
/* "KeyPress" events are those that would be generated before
* whenever queueing up any KEYBD key via qdevice.
*/
case KeyPress:
/* save out which unmodified key (i.e. the key was
* not modified w/something like "Shift", "Ctrl",
* or "Alt") got pressed for use below.
*/
XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
myKeyPress = TRUE;
break;
} /* end switch (event.type) */
} while (XPending(dpy)); /* end "do { } while".
* XPending() is like qtest()--it only
* tells you if there're any events
* presently in the queue. it does not
* disturb queue's contents in any way.
*/
/* On an "Expose" event, redraw the affected pop'd or de-iconized window
*/
if (myExpose) {
resize_buffer();
myExpose = FALSE; /* reset flag--queue now empty */
}
/* On a "ConfigureNotify" event, the GL window has either been moved or
* resized. Respond accordingly and then redraw its contents.
*/
if (myConfigure) {
oxpos = xpos;
oypos = ypos;
resize_buffer();
myConfigure = FALSE; /* reset flag--queue now empty */
}
if (needToDraw) {
drawScene();
needToDraw = FALSE;
}
/* On a keypress of Esc key, exit program.
*/
if (myKeyPress) {
if (keysym == XK_Escape)
clean_exit();
}
if (myButtPress) {
orient();
drawScene();
myButtPress = FALSE;
}
} /* end while(1) */
} /* end main */
static int attributeList[] = { GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None };
static int attributeList2[] = { GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None };
static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
}
XSizeHints Winhints; /* used to fix window size */
/* openwindow -
* establish connection to X server, get screen info, specify the
* attributes we want the WM to try to provide, and create the GL window
*/
void openwindow(char *progname) {
XVisualInfo *vi;
GLXContext cx;
Colormap cmap;
XSizeHints Winhints; /* used to fix window size */
XSetWindowAttributes swa;
int scrnnum; /* X screen number */
int xorig, yorig; /* window (upper-left) origin */
long scrnheight;
/* define window initial size */
xorig = 50; yorig = 40;
xsize = 300; ysize = 240;
scrnaspect = xsize / (double) ysize;
/* Connect to the X server and get screen info */
if ((dpy = XOpenDisplay(NULL)) == NULL) {
fprintf(stderr, "%s: cannot connect to X server %s\n",
progname, XDisplayName(NULL));
exit(1);
}
scrnnum = DefaultScreen(dpy);
scrnheight = DisplayHeight(dpy, scrnnum);
/* get an appropriate visual */
vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
if (vi == NULL) {
fprintf(stderr, "Unable to obtain Doublebuffered visual; ");
fprintf(stderr, "now going for singlebuffer'd...\n");
vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
}
if (vi == NULL) {
printf("Unable to obtain Singlebuffered VISUAL(????)\n");
exit(0);
}
/* create a GLX context */
cx = glXCreateContext(dpy, vi, None, GL_TRUE);
/* create a colormap */
cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
vi->visual, AllocNone);
/* create a window */
swa.colormap = cmap;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask | ButtonPressMask | ExposureMask |
Button1MotionMask | KeyPressMask; /* express interest in events */;
glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
xorig, yorig, xsize, ysize,
0, vi->depth, InputOutput, vi->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa);
XMapWindow(dpy, glwin);
XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
/* connect the context to the window */
glXMakeCurrent(dpy, glwin, cx);
if (!(glwin)) {
fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
exit(1);
}
/* define string that will show up in the window title bar (and icon) */
XStoreName(dpy, glwin, "z-buffered rgb program");
/* specify the values for the Window Size Hints we want to enforce: this
* window's aspect ratio needs to stay at 1:1, constrain min and max
* window size, and specify the initial size of the window.
*/
Winhints.width = xsize; /* specify desired x/y size of window */
Winhints.height = ysize;
Winhints.min_width = xorig; /* define min and max */
Winhints.max_width = scrnheight-1; /* width and height */
Winhints.min_height = yorig;
Winhints.max_height = scrnheight-1;
Winhints.min_aspect.x = xsize; /* keep aspect to a xsize:ysize ratio */
Winhints.max_aspect.x = xsize;
Winhints.min_aspect.y = ysize;
Winhints.max_aspect.y = ysize;
Winhints.flags = USSize|PMaxSize|PMinSize|PAspect; /* set the */
XSetNormalHints(dpy, glwin, &Winhints); /* corresponding flags */
/* express interest in WM killing this app */
if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
XSetWMProtocols(dpy, glwin, &del_atom, 1);
return ;
}
/* window has been moved or resized so update viewport & CTM stuff.
*/
void resize_buffer() {
XSync(dpy, False); /* STILL NEED THIS????? *//* Need before GL reshape */
scrnaspect = xsize / (double) ysize;
glViewport(0, 0, xsize-1, ysize-1);
}
/* clean up before exiting
*/
void clean_exit(void)
{
XCloseDisplay(dpy);
exit(0);
}
/* setup all necessary GL initialzation parameters.
*/
void initGL()
{
glEnable(GL_DEPTH_TEST);
glClearColor(0.16, 0.39, 0.78, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluPerspective(400.0, scrnaspect, 30.0, 1000.0);
}
void orient()
{
float dx, dy;
glPushMatrix();
dx = xpos-oxpos;
dy = oypos-ypos;
glLoadIdentity();
glRotatef((float) (0.03*(xpos-oxpos)), 1.0, 0.0, 0.0);
glRotatef((float) (0.03*(oypos-ypos)), 0.0, 1.0, 0.0);
glMultMatrixf(objmat);
glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
glPopMatrix();
}
void drawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0, 0.0, -40.0);
glMultMatrixf(objmat);
glRotatef(-220.0, 0.0, 1.0, 0.0); /* skews orig view to show all polys */
drawPolys();
glPopMatrix();
glFlush ();
glXSwapBuffers(dpy, glwin);
}
float polygon1[3][3] = { {-10.0, -10.0, 0.0,},
{ 10.0, -10.0, 0.0,},
{-10.0, 10.0, 0.0,} };
float polygon2[3][3] = { { 0.0, -10.0, -10.0,},
{ 0.0, -10.0, 10.0,},
{ 0.0, 5.0, -10.0,} };
float polygon3[4][3] = { {-10.0, 6.0, 4.0,},
{-10.0, 3.0, 4.0,},
{ 4.0, -9.0, -10.0,},
{ 4.0, -6.0, -10.0,} };
void drawPolys()
{
glBegin(GL_POLYGON);
glColor4f(0.0, 0.0, 0.0, 0.0);
glVertex3fv(&polygon1[0][0]);
glColor4f(0.5, 0.5, 0.5, 0.0);
glVertex3fv(&polygon1[1][0]);
glColor4f(1.0, 1.0, 1.0, 0.0);
glVertex3fv(&polygon1[2][0]);
glEnd();
glBegin(GL_POLYGON);
glColor4f(1.0, 1.0, 0.0, 0.0);
glVertex3fv(&polygon2[0][0]);
glColor4f(0.0, 1.0, 0.5, 0.0);
glVertex3fv(&polygon2[1][0]);
glColor4f(0.0, 0.0, 1.0, 0.0);
glVertex3fv(&polygon2[2][0]);
glEnd();
glBegin(GL_POLYGON);
glColor4f(1.0, 1.0, 0.0, 0.0);
glVertex3fv(&polygon3[0][0]);
glColor4f(1.0, 0.0, 1.0, 0.0);
glVertex3fv(&polygon3[1][0]);
glColor4f(0.0, 0.0, 1.0, 0.0);
glVertex3fv(&polygon3[2][0]);
glColor4f(1.0, 0.0, 1.0, 0.0);
glVertex3fv(&polygon3[3][0]);
glEnd();
}